//
//  IFlyIVWStreamService.m
//  AIKITDemo
//
//  Created by xyzhang on 2023/3/16.
//

#import "IFlyIVWStreamService.h"
#import "IFlyDebugLog.h"
#import "IVWEngine.h"

@interface IFlyIVWStreamService ()<IFlyWakeupEngineDelegate>
{
    int                                 _error;
    int                                 _isSpeechEnd;//确保onEndOfSpeech回调只被调用一次
    int                                 _netTimeout;//最长等待时间
    BOOL                                _oneshot;
    BOOL                                _isRecognizing;//当前正处于oneshot识别阶段
    NSDate                              *_startDate;//开始时间
    NSDate                              *_stopDate;//结束时间
}

@property (nonatomic, weak) id<IFlyVoiceWakeupDelegate> delegate;

@property (nonatomic, strong) IVWEngine *ivwEngine;

@property (nonatomic, strong) IFlyIVWConfig *ivwConfig;

@property (nonatomic, assign) IVWState state;//引擎状态

@end

@implementation IFlyIVWStreamService

- (instancetype)initWithDelegate:(id<IFlyVoiceWakeupDelegate>)delegate withConfig:(IFlyIVWConfig *)config {
    
    if (self = [super init]) {
        _delegate = delegate;
        _ivwConfig = config;
        _state = IVWNoInit;
        _isSpeechEnd = NO;
    
        _ivwEngine = [[IVWEngine alloc] init];
        [_ivwEngine setConfig:config];
        [_ivwEngine setDelegate:self];
        
        _oneshot = NO;
        
//        NSString *sst = [_ivwConfig valueForKey:[IFlySpeechConstant IVW_SST]];
//        if([sst length] > 0){
//            if(NSOrderedSame == [sst compare:[IFlySpeechConstant IVW_ONESHOT]]){
//                _oneshot = YES;
//            }
//        }
        
    }
    return self;
}

- (BOOL)startListening {
    
    [IFlyDebugLog showLog:@"%s [IN]", __func__];
    
    @synchronized (self) {
        
        [IFlyDebugLog showLog:@"%s [IN],self=%", __func__, self];
        
        int bRet = [_ivwEngine startEngine];
        if (bRet) {
            
            [IFlyDebugLog showLog:@"%s [OUT], _error=%d", __func__, _error];
            _error = bRet;
            return bRet;
        }
        
        [self setState:IVWInit];
        [IFlyDebugLog showLog:@"%s [OUT]", __func__];
        return YES;
    }
    
    
}

- (BOOL)stopWrite {
    
    [IFlyDebugLog showLog:@"%s [IN],_error=%d",__func__,_error];
    
    @synchronized (self) {
        
        if (_error != 0) {
            return NO;
        }
        
        //已经start，但是没有送入音频
        if (_state == IVWInit) {
            [self setState:IVWEnd];
        }
        else if(_state == IVWRecording) {//已经送入音频
            [self writeEndData];
            [self setState:IVWWakeuping];
        }
    }//@synchronized
    
    [IFlyDebugLog showLog:@"%s[OUT]",__func__];
    
    return YES;
}


- (BOOL)writeAudio:(NSData *)audioData {
    
    [IFlyDebugLog showLog:@"%s [IN], _error=%d, length=%d, state=%d", __func__, _error, audioData.length, _state];
    
    @synchronized (self) {
        
        //仅仅限制状态为已经初始化或者正在传入数据时方可
        if (!(_state == IVWRecording || _state == IVWInit)) {
            return NO;
        }
        
        //出错时停止写入数据
        if (_error) {
            return NO;
        }
        
        if (!_ivwEngine) {
            return NO;
        }
        
        //数据长度为0时停止写入数据
        if(audioData.length == 0){
            return NO;
        }
        
        [self setState:IVWRecording];
        
        int err = 0;
        
        err = [_ivwEngine writeAudio:(const char*)([audioData bytes]) length:(unsigned int)[audioData length] audioStatus:1];
        
        if (err != 0) {
            _error = err;
            
            if (!_isSpeechEnd) {
                _isSpeechEnd = YES;
                
                if (_delegate && [_delegate respondsToSelector:@selector(onEndOfSpeech)]) {
                    [_delegate onEndOfSpeech];
                }
            }
            
            [self setState:IVWEnd];
            
            [IFlyDebugLog showLog:@"%s[OUT],_error=%d",__func__,_error];
        }
    }
    
    return YES;
}

- (void) cancel{
    
    [IFlyDebugLog showLog:@"%s[IN], _error=%d", __func__, _error];
    
    @synchronized (self) {
        
        if(_state == IVWInit || _state == IVWInit || _state == IVWWakeuping) {
            if(_state == IVWRecording) {
                if (!_isSpeechEnd) {
                    _isSpeechEnd = YES;
                    
                    if (_delegate && [_delegate respondsToSelector:@selector(onEndOfSpeech)]) {
                        [_delegate onEndOfSpeech];
                    }
                }
            }
            
            [self setState:IVWEnd];
        }
        
        [IFlyDebugLog showLog:@"%s[OUT]",__func__];
    }
}

#pragma mark - Private

- (void)setState:(IVWState)state {
    
    if(state == _state){
        return;
    }
    
    @synchronized(self) {
        _state = state;
    }
    
    switch (_state) {
        case IVWRecording: {
            if (_delegate && [_delegate respondsToSelector:@selector(onBeginOfSpeech)]) {
                [_delegate onBeginOfSpeech];
            }
        }
            break;
        case IVWWakeuping: {
            if (!_isSpeechEnd) {
                _isSpeechEnd = YES;
                
                if (_delegate && [_delegate respondsToSelector:@selector(onEndOfSpeech)]) {
                    [_delegate onEndOfSpeech];
                }
            }
            
            dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
                [self setState:IVWEnd];
            });
            
        }
            break;
        case IVWCanceling:
            break;
        case IVWEnd: {
            [IFlyDebugLog showLog:@"%s [IVWEnd IN]",__func__];
            
            dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
                [self ivwEndDeal];
            });
            
            [IFlyDebugLog showLog:@"%s [IVWEnd OUT]",__func__];
        }
            break;
        default:
            break;
    }
}

- (void)ivwEndDeal {
    //耗时过长，异步处理
    if (self.ivwEngine) {
        [_ivwEngine stopEngine];
        _ivwEngine.delegate = nil;
    }
    
    if (_delegate && [_delegate respondsToSelector:@selector(onCompletedWithErrorCode:)]) {
        [_delegate onCompletedWithErrorCode:_error];
    }
}

- (void)writeEndData {
    //写入尾数据，这是msc的规范，告诉识别引擎数据已经写入完成
    //aikit 只要调用 AiHelper end告诉引擎结束就行,不需要写入结束帧
//    [_ivwEngine writeAudio:NULL length: 0 audioStatus:MSP_AUDIO_SAMPLE_LAST];
}


#pragma mark - IFlyWakeupEngineDelegate

// 错误码返回
- (void)onWakeupEngineRunEndDelegate:(int)errorCode {
    
    [IFlyDebugLog showLog:@"%s,eror=%d",__func__,errorCode];
    
    if (errorCode) {
        _error = errorCode;
    }
    
    //音频数据传入结束回调
    if (_state == IVWRecording) {
        if (!_isSpeechEnd) {
            _isSpeechEnd = YES;
            
            if (_delegate && [_delegate respondsToSelector:@selector(onEndOfSpeech)]) {
                [_delegate onEndOfSpeech];
            }
        }
    }
    
    [self setState:IVWEnd];
}

/*
 * 停止录音等待结果
 */
- (BOOL)onWakeupEngineStopAndWaitResultDelegate {
    
    [IFlyDebugLog showLog:@"%s,self.state=%d",__func__,self.state];
    
    _isRecognizing = YES;
    
    if (self.state == IVWRecording) {
        //写入尾数据
        [self writeEndData];
        //等待识别结果
        [self setState:IVWWakeuping];
    }
    
    return YES;
}

/*
 * 唤醒结果回调
 */
-(void)onWakeupEngineGetResultDelegate:(NSString *)result {
    
    [IFlyDebugLog showLog:@"%s,self.state=%d",__func__,self.state];
    
    if(_delegate && [_delegate respondsToSelector:@selector(onResultStr:)]) {
        [_delegate onResultStr:result];
    }
    
}

- (void)onWakeupEngineOnEvent:(int)eventType isLast:(BOOL)isLast arg1:(int)arg1 data:(NSString *)eventData {
    // event pass
}

@end
